Three.js OrbitControls绕环旋转 您所在的位置:网站首页 threejs render Three.js OrbitControls绕环旋转

Three.js OrbitControls绕环旋转

2023-04-24 11:36| 来源: 网络整理| 查看: 265

通常,对于第三人称相机,您需要不断地将相机对准玩家(或距玩家的某个偏移量,或附加在玩家上的某个物体)。

然后你让相机跟随玩家一段时间。

在下面的代码中,播放器后面有一个cameraRig。相机装置在那里,所以我们不需要做任何数学运算来保持相机在地面上。类似地,还有一个连接到播放器的camTarget。这是为了让相机看起来和肩膀一样高。

function main() { const canvas = document.querySelector('#c'); const renderer = new THREE.WebGLRenderer({canvas}); const keys = {}; const scene = new THREE.Scene(); const fov = 75; const aspect = 2; // the canvas default const near = 0.1; const far = 500; const camera = new THREE.PerspectiveCamera(fov, aspect, near, far); // put the camera 5 units above the rig const cameraRig = new THREE.Object3D(); cameraRig.add(camera); camera.position.y = 5; scene.add(cameraRig); cameraRig.position.z = 5; { const color = 0xFFFFFF; const intensity = 1; const light = new THREE.DirectionalLight(color, intensity); light.position.set(-1, 2, 4); scene.add(light); } { const size = 200; const divisions = 100; const gridHelper = new THREE.GridHelper(size, divisions); scene.add(gridHelper); } const boxWidth = 0.5; const boxHeight = 2; const boxDepth = 0.5; const geometry = new THREE.CylinderGeometry(boxWidth, boxDepth, boxHeight); const material = new THREE.MeshPhongMaterial({color:'red'}); const cube = new THREE.Mesh(geometry, material); const player = new THREE.Object3D(); const camTarget = new THREE.Object3D(); cube.position.y = boxHeight / 2; // move cube above ground player.add(cube); camTarget.position.y = boxHeight * 3 / 2; // target 2/3ds up the player player.add(camTarget); scene.add(player); function resizeRendererToDisplaySize(renderer) { const canvas = renderer.domElement; const width = canvas.clientWidth; const height = canvas.clientHeight; const needResize = canvas.width !== width || canvas.height !== height; if (needResize) { renderer.setSize(width, height, false); } return needResize; } const moveDir = new THREE.Vector3(); const camTargetPos = new THREE.Vector3(); let then = 0; function render(now) { now *= 0.001; deltaTime = now - then; then = now; if (resizeRendererToDisplaySize(renderer)) { const canvas = renderer.domElement; camera.aspect = canvas.clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(); } // left, right, a, d const dx = ((keys[37] || keys[65]) ? 1 : 0) + ((keys[39] || keys[68]) ? -1 : 0); // up, down, w, s const dy = ((keys[38] || keys[87]) ? 1 : 0) + ((keys[40] || keys[83]) ? -1 : 0); const playerMoveSpeed = 10; // units per second camera.getWorldDirection(moveDir); moveDir.y = 0; // no up down movement moveDir.normalize(); // move player forward/back player.position.addScaledVector(moveDir, dy * playerMoveSpeed * deltaTime); // rotate direction 90 degrees const t = moveDir.x; moveDir.x = moveDir.z; moveDir.z = -t; // move player left/right player.position.addScaledVector(moveDir, dx * playerMoveSpeed * deltaTime); // if the cameraRig is too far from // player then move it const maxDistance = 6; const maxCamMoveSpeed = 0.015; const distance = cameraRig.position.distanceTo(player.position); if (distance > maxDistance) { const amount = maxCamMoveSpeed; cameraRig.position.lerp(player.position, amount); } camTarget.getWorldPosition(camTargetPos); camera.lookAt(camTargetPos); renderer.render(scene, camera); requestAnimationFrame(render); } requestAnimationFrame(render); window.addEventListener('keydown', (e) => { e.preventDefault(); keys[e.keyCode] = true; }); window.addEventListener('keyup', (e) => { e.preventDefault(); keys[e.keyCode] = false; }); } main();body { margin: 0; } #c { width: 100vw; height: 100vh; display: block; }

第三人称相机可能很难。上面的这个太简单了。您可以将其想象为cameraRig被拖到播放器后面的字符串上。如果你倒回去,摄像机就不动了。只有当相机处于maxDistance状态时它才会移动。

通常是把相机放在一根棍子上,这样如果你向后走,棍子就会把相机向后推。

function main() { const canvas = document.querySelector('#c'); const renderer = new THREE.WebGLRenderer({canvas}); const keys = {}; const scene = new THREE.Scene(); const fov = 75; const aspect = 2; // the canvas default const near = 0.1; const far = 500; const camera = new THREE.PerspectiveCamera(fov, aspect, near, far); // put the camera 5 units above the rig const cameraRig = new THREE.Object3D(); cameraRig.add(camera); camera.position.y = 5; scene.add(cameraRig); cameraRig.position.z = 5; { const color = 0xFFFFFF; const intensity = 1; const light = new THREE.DirectionalLight(color, intensity); light.position.set(-1, 2, 4); scene.add(light); } { const size = 200; const divisions = 100; const gridHelper = new THREE.GridHelper(size, divisions); scene.add(gridHelper); } const boxWidth = 0.5; const boxHeight = 2; const boxDepth = 0.5; const geometry = new THREE.CylinderGeometry(boxWidth, boxDepth, boxHeight); const material = new THREE.MeshPhongMaterial({color:'red'}); const cube = new THREE.Mesh(geometry, material); const player = new THREE.Object3D(); const camTarget = new THREE.Object3D(); cube.position.y = boxHeight / 2; // move cube above ground player.add(cube); camTarget.position.y = boxHeight * 3 / 2; // target 2/3ds up the player player.add(camTarget); scene.add(player); function resizeRendererToDisplaySize(renderer) { const canvas = renderer.domElement; const width = canvas.clientWidth; const height = canvas.clientHeight; const needResize = canvas.width !== width || canvas.height !== height; if (needResize) { renderer.setSize(width, height, false); } return needResize; } const moveDir = new THREE.Vector3(); const camTargetPos = new THREE.Vector3(); const rigTargetPos = new THREE.Vector3(); function moveCameraToDistance(desiredDistance) { const maxCamMoveSpeed = 0.02; // delta from player to rig rigTargetPos.subVectors(cameraRig.position, player.position); // remove up/down rigTargetPos.y = 0; // no up/down // make unit vector rigTargetPos.normalize(); // make desiredDistance long rigTargetPos.multiplyScalar(desiredDistance); // add player position rigTargetPos.add(player.position); // move rig toward that position const curDistance = cameraRig.position.distanceTo(player.position); cameraRig.position.lerp( rigTargetPos, THREE.MathUtils.lerp( maxCamMoveSpeed, 1, THREE.MathUtils.clamp(1 - curDistance / desiredDistance, 0, 1))); } let then = 0; function render(now) { now *= 0.001; deltaTime = now - then; then = now; if (resizeRendererToDisplaySize(renderer)) { const canvas = renderer.domElement; camera.aspect = canvas.clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(); } // left, right, a, d const dx = ((keys[37] || keys[65]) ? 1 : 0) + ((keys[39] || keys[68]) ? -1 : 0); // up, down, w, s const dy = ((keys[38] || keys[87]) ? 1 : 0) + ((keys[40] || keys[83]) ? -1 : 0); const playerMoveSpeed = 10; // units per second camera.getWorldDirection(moveDir); moveDir.y = 0; // no up down movement moveDir.normalize(); // move player forward/back player.position.addScaledVector(moveDir, dy * playerMoveSpeed * deltaTime); // rotate direction 90 degrees const t = moveDir.x; moveDir.x = moveDir.z; moveDir.z = -t; // move player left/right player.position.addScaledVector(moveDir, dx * playerMoveSpeed * deltaTime); // keep camera at distance const minDistance = 4; const maxDistance = 6; const distance = cameraRig.position.distanceTo(player.position); if (distance > maxDistance) { moveCameraToDistance(maxDistance); } else if (distance < minDistance) { moveCameraToDistance(minDistance); } // compute point from player in direction of rig // at desired distance camTarget.getWorldPosition(camTargetPos); camera.lookAt(camTargetPos); renderer.render(scene, camera); requestAnimationFrame(render); } requestAnimationFrame(render); window.addEventListener('keydown', (e) => { e.preventDefault(); keys[e.keyCode] = true; }); window.addEventListener('keyup', (e) => { e.preventDefault(); keys[e.keyCode] = false; }); } main();body { margin: 0; } #c { width: 100vw; height: 100vh; display: block; }

然后你需要处理一些东西,比如在相机和播放器之间的东西。(有些游戏会淡出这些东西)。你还需要处理,比如说走进一扇门。有一段时间,玩家会在门的一边,相机在门的另一边(或者更确切地说,在门的另一边),所以相机下来了,所以它可以透过门看到吗?墙会淡出吗?摄像机是否会跳过门,开始从其他位置观察。有传言说,64岁的马里奥有一位程序员,他花了整整一年的时间在相机上工作,除此之外什么也没干。)

请注意,上面的某些代码仅适用于someObject.position是世界空间位置的特殊情况(对象没有父对象,或者如果它有父对象,则所有父对象的位置= 0,0,0旋转= 0,0,0,比例= 1,1,1)。如果对象确实有父对象,则需要使用以下命令获取世界位置

const wp = new THREE.Vector3(); someObject.getWorldPosition(wp);

如果你想应用一个世界位置,你需要做更多的工作来使这个位置相对于父对象。现在,为了简单起见,我只使用了对象,对象的世界位置就是它们的位置。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有